package com.example.houseitemmanagebackend.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Collections;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * Redis缓存工具类
 * 提供安全的Redis操作方法，处理潜在的Redis连接异常
 */
public class RedisCacheUtils {

    private static final Logger log = LoggerFactory.getLogger(RedisCacheUtils.class);

    /**
     * 安全地从Redis获取值，如果发生异常则回退到提供的supplier
     * 
     * @param redisTemplate Redis模板
     * @param key           缓存键
     * @param supplier      数据提供者，在缓存未命中或出错时使用
     * @param <T>           数据类型
     * @return 缓存值或supplier提供的值
     */
    public static <T> T getWithFallback(RedisTemplate<String, Object> redisTemplate, String key, Supplier<T> supplier) {
        try {
            Object value = redisTemplate.opsForValue().get(key);
            if (value != null) {
                return (T) value;
            }
        } catch (Exception e) {
            log.error("从Redis获取数据失败，key: {}，错误: {}", key, e.getMessage());
        }

        return supplier.get();
    }

    /**
     * 安全地将值存入Redis
     * 
     * @param redisTemplate Redis模板
     * @param key           缓存键
     * @param value         缓存值
     * @param timeout       过期时间
     * @param unit          时间单位
     * @return 是否成功缓存
     */
    public static boolean setWithRetry(RedisTemplate<String, Object> redisTemplate, String key, Object value,
            long timeout, TimeUnit unit) {
        try {
            redisTemplate.opsForValue().set(key, value, timeout, unit);
            return true;
        } catch (Exception e) {
            log.error("向Redis写入数据失败，key: {}，错误: {}", key, e.getMessage());
            return false;
        }
    }

    /**
     * 安全地删除Redis缓存
     * 
     * @param redisTemplate Redis模板
     * @param key           缓存键
     * @return 是否成功删除
     */
    public static boolean delete(RedisTemplate<String, Object> redisTemplate, String key) {
        try {
            return Boolean.TRUE.equals(redisTemplate.delete(key));
        } catch (Exception e) {
            log.error("删除Redis缓存失败，key: {}，错误: {}", key, e.getMessage());
            return false;
        }
    }

    /**
     * 安全地使用模式删除Redis缓存
     * 
     * @param redisTemplate Redis模板
     * @param pattern       模式字符串
     * @return 删除的键的数量
     */
    public static long deleteByPattern(RedisTemplate<String, Object> redisTemplate, String pattern) {
        try {
            Set<String> keys = redisTemplate.keys(pattern);
            if (keys != null && !keys.isEmpty()) {
                Long count = redisTemplate.delete(keys);
                return count != null ? count : 0;
            }
        } catch (Exception e) {
            log.error("通过模式删除Redis缓存失败，pattern: {}，错误: {}", pattern, e.getMessage());
        }
        return 0;
    }

    /**
     * 安全地获取匹配模式的所有键
     * 
     * @param redisTemplate Redis模板
     * @param pattern       模式字符串
     * @return 匹配的键集合
     */
    public static Set<String> getKeysByPattern(RedisTemplate<String, Object> redisTemplate, String pattern) {
        try {
            Set<String> keys = redisTemplate.keys(pattern);
            return keys != null ? keys : Collections.emptySet();
        } catch (Exception e) {
            log.error("获取Redis键失败，pattern: {}，错误: {}", pattern, e.getMessage());
            return Collections.emptySet();
        }
    }
}